package ca.etsmtl.log430.lab3.gestion;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import ca.etsmtl.log430.lab3.donnee.ReaderFactory;
import ca.etsmtl.log430.lab3.donnee.beans.*;
import ca.etsmtl.log430.lab3.donnee.ifaces.CourseReader;
import ca.etsmtl.log430.lab3.donnee.ifaces.TeacherReader;
import ca.etsmtl.log430.lab3.donnee.txtreader.FileTeacherReader;
import ca.etsmtl.log430.lab3.gestion.ifaces.*;
import ca.etsmtl.log430.lab3.gestion.list.CourseList;
import ca.etsmtl.log430.lab3.gestion.list.TeacherList;
/**
 * 
 * @author samuel
	 *Modification 4: Modifier le syst�me de telle sorte qu'une v�rification de conflits soit effectu�e. V�rifiez 
	sp�cifiquement pour les types de conflits suivants: 
	
	 conflit d'horaire � vous devez v�rifier � chaque fois que le cours ou laboratoire qu�on assigne � un 
	 enseignant n'entre pas en conflit avec un autre  cours ou laboratoire d�j� assign� au m�me enseignant. 
	 
	limite de cours � attribuer � un enseignant � si l�enseignant a le statut de professeur (PRF), on ne 
	peut lui assigner plus de trois (3) cours dans une m�me ann�e. Si l�enseignant est un charg� de 
	cours (CHR), on ne peut lui assigner plus de cinq (5) cours dans une m�me ann�e. Notez que les 
	laboratoires n'affectent pas cette r�gle, seulement les cours. Un prof peut donner trois cours plus 
	des laboratoires, mais pas plus de trois  cours. Un charg� peut donner cinq cours plus des 
	laboratoires, mais pas plus de cinq cours. 
 */
public class TeacherAssignment implements ITeacherAssignment {
	
	CourseReader myCourseListReader;
	TeacherReader myTeacherListReader;
	ReaderFactory readerFactory;
	TeacherList teacherList;
	CourseList courseList;
	
	/**
	 * 
	 * @param courseFileName
	 * @param teacherFileName
	 */
	public TeacherAssignment(String courseFileName,
			String  teacherFileName) {
		super();
		readerFactory = new ReaderFactory(courseFileName, teacherFileName);
		this.myCourseListReader = readerFactory.getCourseReader();
		this.myTeacherListReader = new FileTeacherReader(teacherFileName);
				
		
		Collection<CourseBean> coursesBeans = myCourseListReader.getListOfCourses();
		Collection<TeacherBean> teacherBeans = myTeacherListReader.getListOfTeachers();
		
		HashMap<Integer,CourseBean> coursesBeansMap = new HashMap<Integer,CourseBean>();
		
		HashMap<Integer,TeacherBean> teacherBeansMap = new HashMap<Integer,TeacherBean>();
		
		for (CourseBean courseBean : coursesBeans) {
			coursesBeansMap.put(courseBean.hashCode(), courseBean);
		}
		
		for (TeacherBean teacherBean : teacherBeans) {
			teacherBeansMap.put(teacherBean.hashCode(), teacherBean);
		}
		
		courseList = new CourseList();
		teacherList = new TeacherList();
		
		TeacherBuilder teacherBuilder = new TeacherBuilder(this);
		
		for (TeacherBean teacherBean : teacherBeans) 
		{
			Teacher t = teacherBuilder.build(teacherBean);
			teacherList.addTeacher(t);
		}
		
		for (CourseBean courseBean : coursesBeans) {
			Course course = CourseBuilder.build(courseBean);
			courseList.addCourse(course);
		}
		
		for (TeacherBean teacherBean : teacherBeans) 
		{
			
			Teacher teacher = teacherList.findTeacherByID(teacherBean.getTeacherID());
			
			Collection<String> coursesIds = teacherBean.getCoursesAssignedList();
			
			for (String courseId : coursesIds) {
				Course course = courseList.findcoursByID(courseId);
				try 
				{
					teacher.assignCourse(course);
				} 
				catch (TeacherAssignmentException e) {
					
					e.printStackTrace();
				}			
			}
			
			coursesIds = teacherBean.getCoursesTaughtList();
			
			for (String courseId : coursesIds) {
				Course course = courseList.findcoursByID(courseId);
				
				teacher.addCourseToBeTaught(courseId);	
			}						
			
		}			
		
	}
	@Override
	public Collection<Course> getListOfCourses() {
		
		courseList.goToFrontOfList();
		ArrayList<Course> courses= new ArrayList<Course>();
		boolean readingList=true;
		while(readingList)
		{
			Course course = courseList.getNextCourse();
			if(null!=course)
				courses.add(course);
			else
				readingList=false;
			
		}
		
		return courses;
		
	}
	
	@Override
	public Collection<Teacher> getListOfTeachers() {
		
		teacherList.goToFrontOfList();
		ArrayList<Teacher> teachers= new ArrayList<Teacher>();
		boolean readingList=true;
		while(readingList)
		{
			Teacher teacher = teacherList.getNextTeacher();
			if(null!=teacher)
				teachers.add(teacher);
			else
				readingList=false;
			
		}
		
		return teachers;
		
	}
	
	/**
	 * 
	 * @param filter
	 * @param collection
	 * @return
	 */
	public <E> Collection<E> getSubList(Filter<E> filter,Collection<E> collection)
	{
		ArrayList<E> result = new ArrayList<E>();
		for (E iterable_element : collection) {
			if(filter.validate(iterable_element))
				result.add(iterable_element);
		}
		
		return result;
	}
	
	@Override
	public Collection<Course> getListOfCoursesNotLab() {
		
		Filter<Course> courseFilter= new Filter<Course>() {	
			@Override
			public boolean validate(Course object) {				
				return !object.getType().equals(CourseType.LAB);
			}
		};
		
		return getSubList(courseFilter,getListOfCourses());
		
	}
	
	@Override
	public Teacher findTeacherByID(String userChoice)  {
		return teacherList.findTeacherByID(userChoice);
	}
	
	@Override
	public Course findCourseByIDActivityAndGroup(String userChoiceCourseID,
			String userChoiceGroup, CourseType userChoiceActivityType) {
		return courseList.findCourseByIDActivityAndGroup(userChoiceCourseID, userChoiceGroup, userChoiceActivityType);
	}

	@Override
	public Course findcoursByID(String string) {
		return courseList.findcoursByID(string);
	}
	@Override
	public Collection<Course> getListOfCoursesGivenBy(String teacherMatricule) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Collection<Teacher> findTeacherByCourseIdAndGroup(String courseId,
			String group) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Collection<Course> getListOfCourseByIds(Collection<String> ids) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Collection<? extends ICourse> getUnAssignedCourses() {
		Filter<Course> courseFilter= new Filter<Course>() {	
			@Override
			public boolean validate(Course object)
			{			
				boolean valid = true;
				if(object.getType().equals(CourseType.LAB))
					valid = false;
				
				if(0!=object.getTeachers().getSize())
					valid = false;
					
				return valid;
			}
		};
		
		return getSubList(courseFilter,getListOfCourses());
		
	}
	@Override
	public void assignTeacherToCourse(Teacher teacher, ICourse course) throws TeacherAssignmentException {
		
		
		teacher.assignCourse(course);
		course.assignTeacher(teacher);
		
	}
	
	
	
} // Class